package managers.dateManager.endFrozen.beginChange;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import junit.framework.TestCase;

import org.apache.log4j.Logger;
import org.tbjd.client.beans.Task;
import org.tbjd.client.constants.NotificationsConstants;
import org.tbjd.client.constants.TimeConstants;
import org.tbjd.client.exceptions.DateManagerException;
import org.tbjd.client.managers.TaskManager;
import org.tbjd.client.states.StateDurationByDates;
import org.tbjd.client.states.StateEndFrozenSPEC;

import factories.TaskFactory;

/**
 * <p>
 * Test TaskManager's methods
 * </p>
 * <p>
 * <b>Case</b>
 * </p>
 * <p>
 * Task with EndDate frozen and no relationships (predecessors/successors)
 * </p>
 * <p>
 * <b> Expected</b>
 * <ul>
 * <li>update Duration</li>
 * <li>update BeginDate</li>
 * </ul>
 * </p>
 * 
 * @author Michael Martin
 * @author Antonio Carrozzini
 * @version 1.0
 * 
 */
public class EndFrozen_BeginChange_UpdateSingleTask_Basic extends TestCase {

	private Task task = null;
	private Map<Integer, Object> map = null;
	private Logger log = Logger.getLogger("console");
	private DateFormat df = DateFormat.getInstance();
	private TaskManager dateManager = new TaskManager();

	protected void setUp() throws Exception {
		df = new SimpleDateFormat("dd.MM.yyyy");
		
		this.task = (Task) TaskFactory.getInstance();
		this.task.setDurationModeByRatios(false);
		task.setState(new StateEndFrozenSPEC(new StateDurationByDates()));
		
		super.setUp();
	}

	public void testListNullity() {
		System.out.println("");
		log.debug(" === testListNullity");
		
		Date newBeginDate = null;
		try {
			newBeginDate = df.parse("1.1.2009");
			
		} catch (ParseException e1) {
			fail(e1.getMessage());
			
		}

		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.TASKMANAGER_ACTION_beginDate, newBeginDate);
		this.map.put(NotificationsConstants.TASKMANAGER_BEAN, task);
		this.map.put(NotificationsConstants.TASKMANAGER_SENDER, null);

		log.debug("call TaskManager...");
		try {
			assertNotNull("Updated bean list isn't null", dateManager.manageDates(map));

		} catch (DateManagerException e) {
			fail(e.getMessage());
			
		}

	}

	public void testListSize() {
		System.out.println("");
		log.debug(" === testListSize");
		
		Date newBeginDate = null;
		try {
			newBeginDate = df.parse("1.1.2009");
			
		} catch (ParseException e1) {
			fail(e1.getMessage());
			
		}
		log.debug("new BeginDate = "+newBeginDate);

		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.TASKMANAGER_ACTION_beginDate, newBeginDate);
		this.map.put(NotificationsConstants.TASKMANAGER_BEAN, task);
		this.map.put(NotificationsConstants.TASKMANAGER_SENDER, null);

		log.debug("call dateManager...");
		List<Task> updatedBeans = null;
		try {
			updatedBeans = dateManager.manageDates(this.map);
			
		} catch (DateManagerException e) {
			fail(e.getMessage());
			
		}
		
		assertTrue(updatedBeans.size() == 1);

	}

	public void testInstanceEquality() {
		System.out.println("");
		log.debug(" === testInstanceEquality");

		Date newBeginDate = null;
		try {
			newBeginDate = df.parse("1.1.2009");
			
		} catch (ParseException e1) {
			fail(e1.getMessage());
			
		}

		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.TASKMANAGER_ACTION_beginDate, newBeginDate);
		this.map.put(NotificationsConstants.TASKMANAGER_BEAN, this.task);
		this.map.put(NotificationsConstants.TASKMANAGER_SENDER, null);

		log.debug("call dateManager...");
		List<Task> updatedBeans = null;
		try {
			updatedBeans = dateManager.manageDates(map);

		} catch (DateManagerException e) {
			fail(e.getMessage());
			
		}

		assertEquals(this.task, updatedBeans.get(0));

	}

	public void testDates() {
		System.out.println("");
		log.debug(" === testDates");

		Date originalEndDate = task.getEndDate();
		Date newBeginDate = null;
		try {
			newBeginDate = df.parse("1.1.2009");

		} catch (ParseException e1) {
			fail(e1.getMessage());
			
		}

		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.TASKMANAGER_ACTION_beginDate, newBeginDate);
		this.map.put(NotificationsConstants.TASKMANAGER_BEAN, task);
		this.map.put(NotificationsConstants.TASKMANAGER_SENDER, null);

		log.debug("call dateManager...");
		List<Task> updatedBeans = null;
		try {
			updatedBeans = dateManager.manageDates(this.map);

		} catch (DateManagerException e) {
			fail(e.getMessage());
			
		}

		assertEquals(newBeginDate, updatedBeans.get(0).getBeginDate());
		assertEquals(originalEndDate, updatedBeans.get(0).getEndDate());

	}

	public void testDurations() {
		System.out.println("");
		log.debug(" === testDurations");

		Date originalBeginDate = task.getBeginDate();
		Date originalEndDate = task.getEndDate();
		float originalDuration = task.getDuration();
		Date newBeginDate = null;
		try {
			newBeginDate = df.parse("31.5.2009");
		} catch (ParseException e1) {
			fail(e1.getMessage());
		}

		log.debug("original beginDate = " + originalBeginDate);
		log.debug("original endDate = " + originalEndDate);
		log.debug("original duration = " + originalDuration);
		log.debug("new BeginDate = " + newBeginDate);

		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.TASKMANAGER_ACTION_beginDate, newBeginDate);
		this.map.put(NotificationsConstants.TASKMANAGER_BEAN, task);
		this.map.put(NotificationsConstants.TASKMANAGER_SENDER, null);

		log.debug("compute with new BeginDate = " + newBeginDate + "...");
		List<Task> updatedBeans = null;
		try {
			updatedBeans = dateManager.manageDates(this.map);

		} catch (DateManagerException e) {
			fail(e.getMessage());
			
		}
		
		log.debug("new duration = " + updatedBeans.get(0).getDuration());

		assertEquals(48f, updatedBeans.get(0).getDuration());

	}

	public void testRevertGivesOriginalBeginDate() {
		System.out.println("");
		log.debug(" === testRevertGivesOriginalBeginDate");

		Date originalBeginDate = task.getBeginDate();
		Date originalEndDate = task.getEndDate();
		float originalDuration = task.getDuration();
		Date newBeginDate = null;
		try {
			newBeginDate = df.parse("1.1.2009");
		} catch (ParseException e1) {
			fail(e1.getMessage());
		}

		log.debug("original beginDate = " + originalBeginDate);
		log.debug("original endDate = " + originalEndDate);
		log.debug("original duration = " + originalDuration);
		log.debug("new BeginDate = " + newBeginDate);

		log.debug("call dateManager with new BeginDate...");
		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.TASKMANAGER_ACTION_beginDate, newBeginDate);
		this.map.put(NotificationsConstants.TASKMANAGER_BEAN, task);
		this.map.put(NotificationsConstants.TASKMANAGER_SENDER, null);

		try {
			dateManager.manageDates(this.map);

		} catch (DateManagerException e) {
			fail(e.getMessage());
			
		}

		log.debug("call dateManager with original BeginDate...");
		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.TASKMANAGER_ACTION_beginDate, originalBeginDate);
		this.map.put(NotificationsConstants.TASKMANAGER_BEAN, task);
		this.map.put(NotificationsConstants.TASKMANAGER_SENDER, null);

		List<Task> updatedBeans = null;
		try {
			updatedBeans = dateManager.manageDates(this.map);

		} catch (DateManagerException e) {
			fail(e.getMessage());
			
		}

		log.debug("retrieved BeginDate = " + updatedBeans.get(0).getBeginDate() + " & original BeginDate = " + originalBeginDate);
		assertEquals("Assert BeginDate reverted to original", originalBeginDate, updatedBeans.get(0).getBeginDate());

	}

	public void testRevertGivesOriginalEndDate() {
		System.out.println("");
		log.debug(" === testRevertGivesOriginalEndDate");

		Date originalBeginDate = task.getBeginDate();
		Date originalEndDate = task.getEndDate();
		float originalDuration = task.getDuration();
		Date newBeginDate = null;
		try {
			newBeginDate = df.parse("1.1.2009");
			
		} catch (ParseException e1) {
			fail(e1.getMessage());
			
		}

		log.debug("original beginDate = " + originalBeginDate);
		log.debug("original endDate = " + originalEndDate);
		log.debug("original duration = " + originalDuration);
		log.debug("new BeginDate = " + newBeginDate);

		log.debug("call dateManager with new BeginDate = " + newBeginDate + "...");
		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.TASKMANAGER_ACTION_beginDate, newBeginDate);
		this.map.put(NotificationsConstants.TASKMANAGER_BEAN, task);
		this.map.put(NotificationsConstants.TASKMANAGER_SENDER, null);

		try {
			dateManager.manageDates(this.map);

		} catch (DateManagerException e) {
			fail(e.getMessage());
			
		}

		log.debug("call dateManager with original BeginDate = " + originalBeginDate + "...");
		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.TASKMANAGER_ACTION_beginDate, originalBeginDate);
		this.map.put(NotificationsConstants.TASKMANAGER_BEAN, task);
		this.map.put(NotificationsConstants.TASKMANAGER_SENDER, null);

		List<Task> updatedBeans = null;
		try {
			updatedBeans = dateManager.manageDates(this.map);

		} catch (DateManagerException e) {
			fail(e.getMessage());
			
		}

		log.debug("retrieved EndDate = " + updatedBeans.get(0).getEndDate() + " & original BeginDate = " + originalEndDate);
		assertEquals("Assert BeginDate reverted to original", originalEndDate, updatedBeans.get(0).getEndDate());

	}

	public void testRevertGivesOriginalDuration() {
		System.out.println("");
		log.debug(" === testRevertGivesOriginalDuration");

		Date originalBeginDate = task.getBeginDate();
		Date originalEndDate = task.getEndDate();
		float originalDuration = task.getDuration();
		Date newBeginDate = null;
		try {
			newBeginDate = df.parse("31.5.2009");
			
		} catch (ParseException e1) {
			fail(e1.getMessage());
			
		}

		log.debug("original beginDate = " + originalBeginDate);
		log.debug("original endDate = " + originalEndDate);
		log.debug("original duration = " + originalDuration);
		log.debug("new BeginDate = " + newBeginDate);

		log.debug("call dateManager with new BeginDate = " + newBeginDate + "...");
		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.TASKMANAGER_ACTION_beginDate, newBeginDate);
		this.map.put(NotificationsConstants.TASKMANAGER_BEAN, task);
		this.map.put(NotificationsConstants.TASKMANAGER_SENDER, null);

		try {
			dateManager.manageDates(this.map);

		} catch (DateManagerException e) {
			fail(e.getMessage());
			
		}

		log.debug("call dateManager with original BeginDate = " + originalBeginDate + "...");
		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.TASKMANAGER_ACTION_beginDate, originalBeginDate);
		this.map.put(NotificationsConstants.TASKMANAGER_BEAN, task);
		this.map.put(NotificationsConstants.TASKMANAGER_SENDER, null);

		List<Task> updatedBeans = null;
		try {
			updatedBeans = dateManager.manageDates(this.map);

		} catch (DateManagerException e) {
			fail(e.getMessage());
			
		}

		assertEquals("Assert Duration reverted to original", originalDuration, updatedBeans.get(0).getDuration());

	}

	public void testBeginDateException() {
		System.out.println("");
		log.debug(" === testBeginDateException");

		Date originalBeginDate = task.getBeginDate();
		Date originalEndDate = task.getEndDate();
		float originalDuration = task.getDuration();
		Date newBeginDate = new Date(task.getEndDate().getTime() + 2 * TimeConstants.DAY_IN_MILLIS);

		log.debug("original beginDate = " + originalBeginDate);
		log.debug("original endDate = " + originalEndDate);
		log.debug("original duration = " + originalDuration);
		log.debug("new BeginDate = " + newBeginDate);

		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.TASKMANAGER_ACTION_beginDate, newBeginDate);
		this.map.put(NotificationsConstants.TASKMANAGER_BEAN, task);
		this.map.put(NotificationsConstants.TASKMANAGER_SENDER, null);

		log.debug("compute with new BeginDate = " + newBeginDate + "...");
		try {
			dateManager .manageDates(this.map);
			fail();

		} catch (DateManagerException e) {
			assertNotNull(e.getMessage());
			
		}
		
	}
	
}